(function(){
	
    var _prevMessenger = window.Messenger;
    var localMessenger;

    localMessenger = window.Messenger = function(){
	
        return localMessenger._call.apply(this, arguments);

    }

    window.Messenger.noConflict = function(){
	
        window.Messenger = _prevMessenger;

        return localMessenger;
    }
})();

window.Messenger._ = (function() {
	
    if (window._)
        return window._

    var ArrayProto = Array.prototype, 
		ObjProto = Object.prototype, 
		FuncProto = Function.prototype;

    
    var push             =  ArrayProto.push,
        slice            =  ArrayProto.slice,
        concat           =  ArrayProto.concat,
        toString         =  ObjProto.toString,
        hasOwnProperty   =  ObjProto.hasOwnProperty;

    
    var nativeForEach      = ArrayProto.forEach,
        nativeMap          = ArrayProto.map,
        nativeReduce       = ArrayProto.reduce,
        nativeReduceRight  = ArrayProto.reduceRight,
        nativeFilter       = ArrayProto.filter,
        nativeEvery        = ArrayProto.every,
        nativeSome         = ArrayProto.some,
        nativeIndexOf      = ArrayProto.indexOf,
        nativeLastIndexOf  = ArrayProto.lastIndexOf,
        nativeIsArray      = Array.isArray,
        nativeKeys         = Object.keys,
        nativeBind         = FuncProto.bind;

   
    var _ = {};

    
    var breaker = {};
  
    var each = _.each = _.forEach = function(obj, iterator, context) {
	
        if (obj == null) return;

        if (nativeForEach && obj.forEach === nativeForEach) {
	
            obj.forEach(iterator, context);

        } else if (obj.length === +obj.length) {
	
            for (var i = 0, l = obj.length; i < l; i++) {
	
                if (iterator.call(context, obj[i], i, obj) === breaker) return;

            }
        } else {
	
            for (var key in obj) {
	
                if (_.has(obj, key)) {
	
                    if (iterator.call(context, obj[key], key, obj) === breaker) return;

                }
            }
        }
    };

    _.result = function(object, property) {
	
        if (object == null) return null;

        var value = object[property];

        return _.isFunction(value) ? value.call(object) : value;
    };

    _.once = function(func) {
	
        var ran = false, memo;

        return function() {
	
            if (ran) return memo;

            ran = true;
            memo = func.apply(this, arguments);
            func = null;

            return memo;
        };
    };

    var idCounter = 0;

    _.uniqueId = function(prefix) {
	
        var id = ++idCounter + '';

        return prefix ? prefix + id : id;
    };

    _.filter = _.select = function(obj, iterator, context) {
	
        var results = [];

        if (obj == null) return results;

        if (nativeFilter && obj.filter === nativeFilter) 
			return obj.filter(iterator, context);
			
        each(obj, function(value, index, list) {
	
            if (iterator.call(context, value, index, list)) 
				results[results.length] = value;
				
        });

        return results;
    };

    
    each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {
       
 			_['is' + name] = function(obj) {
	
            return toString.call(obj) == '[object ' + name + ']';

        };
    });

    _.defaults = function(obj) {
	
        each(slice.call(arguments, 1), function(source) {
	
            if (source) {
	
                for (var prop in source) {
	
                    if (obj[prop] == null) obj[prop] = source[prop];

                }
            }
        });

        return obj;
    };

    _.extend = function(obj) {
	
        each(slice.call(arguments, 1), function(source) {
	
            if (source) {
	
                for (var prop in source) {
	
                    obj[prop] = source[prop];

                }
            }
        });

        return obj;
    };

    _.keys = nativeKeys || function(obj) {
	
        if (obj !== Object(obj)) 
			throw new TypeError('Invalid object');
			
        var keys = [];

        for (var key in obj) 
			if (_.has(obj, key)) 
				keys[keys.length] = key;
				
        return keys;
    };

    _.bind = function(func, context) {
	
        if (func.bind === nativeBind && nativeBind) 
			return nativeBind.apply(func, slice.call(arguments, 1));
			
        var args = slice.call(arguments, 2);

        return function() {
            return func.apply(context, args.concat(slice.call(arguments)));
        };
    };

    _.isObject = function(obj) {
	
        return obj === Object(obj);

    };

    return _;
})();

window.Messenger.Events = (function() {
	
    if (window.Backbone && Backbone.Events) {
	
        return Backbone.Events;
    
	}

    var eventsShim = function() {
	
        var eventSplitter = /\s+/;

        var eventsApi = function(obj, action, name, rest) {
	
            if (!name) return true;

            if (typeof name === 'object') {
	
                for (var key in name) {
	
                    obj[action].apply(obj, [key, name[key]].concat(rest));
                }

            } else if (eventSplitter.test(name)) {
	
                var names = name.split(eventSplitter);

                for (var i = 0, l = names.length; i < l; i++) {
	
                    obj[action].apply(obj, [names[i]].concat(rest));
                }
            } else {
	
                return true;
            }
        };

        var triggerEvents = function(events, args) {
	
            var ev, 
				i = -1, 
				l = events.length;
				
            switch (args.length) {
            	case 0: while (++i < l) (ev = events[i]).callback.call(ev.ctx);
            			return;
            	case 1: while (++i < l) (ev = events[i]).callback.call(ev.ctx, args[0]);
            			return;
            	case 2: while (++i < l) (ev = events[i]).callback.call(ev.ctx, args[0], args[1]);
            			return;
            	case 3: while (++i < l) (ev = events[i]).callback.call(ev.ctx, args[0], args[1], args[2]);
            		    return;
            	default: while (++i < l) (ev = events[i]).callback.apply(ev.ctx, args);
            }
        };

        var Events = {

            on: function(name, callback, context) {
	
                if (!(eventsApi(this, 'on', name, [callback, context]) && callback)) return this;

                this._events || (this._events = {});

                var list = this._events[name] || (this._events[name] = []);

                list.push({callback: callback, context: context, ctx: context || this});

                return this;
            },

            once: function(name, callback, context) {
	
                if (!(eventsApi(this, 'once', name, [callback, context]) && callback)) return this;

                var self = this;

                var once = _.once(function() {
	
                    self.off(name, once);

                    callback.apply(this, arguments);
                });

                once._callback = callback;
                this.on(name, once, context);

                return this;
            },

            off: function(name, callback, context) {
	
                var list, 
					ev, 
					events, 
					names, 
					i, 
					l, 
					j, 
					k;
					
                if (!this._events || !eventsApi(this, 'off', name, [callback, context])) return this;

                if (!name && !callback && !context) {
	
                    this._events = {};
                 
   					return this;
                }

                names = name ? [name] : _.keys(this._events);

                for (i = 0, l = names.length; i < l; i++) {
	
                    name = names[i];

                    if (list = this._events[name]) {
	
                        events = [];

                        if (callback || context) {
	
                            for (j = 0, k = list.length; j < k; j++) {
	
                                ev = list[j];

                                if ((callback && callback !== ev.callback &&
                                                                 callback !== ev.callback._callback) ||
                                        (context && context !== ev.context)) {
	
                                    events.push(ev);
                                }
                            }
                        }

                        this._events[name] = events;
                    }
                }

                return this;
            },

            trigger: function(name) {
	
                if (!this._events) return this;

                var args = Array.prototype.slice.call(arguments, 1);

                if (!eventsApi(this, 'trigger', name, args)) return this;

                var events = this._events[name];
                var allEvents = this._events.all;

                if (events) triggerEvents(events, args);

                if (allEvents) triggerEvents(allEvents, arguments);

                return this;
            },

            listenTo: function(obj, name, callback) {
	
                var listeners = this._listeners || (this._listeners = {});

                var id = obj._listenerId || (obj._listenerId = _.uniqueId('l'));

                listeners[id] = obj;

                obj.on(name, typeof name === 'object' ? this : callback, this);

                return this;
            },

            stopListening: function(obj, name, callback) {
	
                var listeners = this._listeners;

                if (!listeners) return;

                if (obj) {
	
                    obj.off(name, typeof name === 'object' ? this : callback, this);

                    if (!name && !callback) delete listeners[obj._listenerId];
                } else {
	
                    if (typeof name === 'object') callback = this;

                    for (var id in listeners) {
	
                        listeners[id].off(name, callback, this);
                    }

                    this._listeners = {};
                }

                return this;
            }
        };

        Events.bind   = Events.on;
        Events.unbind = Events.off;

        return Events;
    };

    return eventsShim();
})();

(function() {
  var $, 
	  ActionMessenger, 
	  BaseView, 
	  Events, 
	  RetryingMessage, 
	  _, 
	  _Message, 
	  _Messenger, 
	  _ref, 
	  _ref1, 
	  _ref2,
      __hasProp = {}.hasOwnProperty,
      __extends = function(child, parent) { 
	
						for (var key in parent) { 
							
							if (__hasProp.call(parent, key)) 
								child[key] = parent[key]; 
							} 
							
							function ctor() { this.constructor = child; } 
							ctor.prototype = parent.prototype; 
							child.prototype = new ctor(); 
							child.__super__ = parent.prototype; 
							
							return child; 
				},
     __slice = [].slice,
     __indexOf = [].indexOf || function(item) { 
								
									for (var i = 0, l = this.length; i < l; i++) { 
										
										if (i in this && this[i] === item) 
										
										return i; 
									} 
									
								 return -1; 
								
							 };

  	$ = jQuery;

    _ = (_ref = window._) != null ? _ref : window.Messenger._;

    Events = (_ref1 = typeof Backbone !== "undefined" && Backbone !== null ? Backbone.Events : void 0) != null ? _ref1 : window.Messenger.Events;
	
	BaseView = (function(){
			
			function BaseView(options){
				
				$.extend(this, Events);
				
				if(_.isObject(options)){
					
					if(options.el){
						
						this.setElement(options.el);
						
					}
					
					this.model = options.model;
				}
				
				this.initialize.apply(this, arguments);
				
			}
			
			BaseView.prototype.setElement = function(el){
				
				this.$el = $(el);
				
				return this.el = this.$el[0];
				
			}
			
			BaseView.prototype.delegateEvents = function(events){
				
				var delegateEventSplitter,
					eventName,
					key,
					match,
					method,
					selector,
					_results;
					
					if(!(events || (events = _.result(this, 'events')))){
						return;
					}
					
					this.undelegateEvents();
					
					delegateEventSplitter = /^(\S+)\s*(.*)$/;
					
					_results = [];
					
					for(key in events) {
						
						method = events[key];
						
						if(!_.isFunction(method)){
							
							method = this[events[key]];
						}
						
						if(!method){
							throw new Error('Method ' + events[key] + ' does not exist' );
						}
						
						match = key.match(delegateEventSplitter);
						eventName = match[1];
						selector = match[2];
						method = _.bind(method, this);
						eventName += ".delegateEvents" + this.cid;
						
						if(selector === ''){
							
							_results.push(this.jqon(eventName, method));
							
						} else {
							
							_results.push(this,jqon(eventName, selector, method));
							
						}
					}
					
					return _results;
			};
			
			BaseView.prototype.jqon = function(eventName, selector, method){
				
				var _ref2;
				
				if(this.$el.on != null){
					
					return (_ref2 = this.$el).on.apply(_ref2, arguments);
					
				} else {
					
					if(!(method) != null){
						
						method = selector;
						selector = void 0;
						
					}
					
					if(selector != null){
						
						return this.$el.delegate(selector, eventName, method);
						
					} else {
						
						return this.$el.bind(eventName, method);
						
					}
				}
			};
			
			BaseView.prototype.jqoff = function(eventName){
				
				var _ref2;
				
				if(this.$el.off != null){
					
					return (_ref2 = this.$el).off.apply(_ref2, arguments);
				} else {
					
					this.$el.undelegate();
					
					return this.$el.unbind(eventName);
				}
			};
			
			BaseView.prototype.undelegateEvents = function(){
				
				return this.jqoff(".delegateEvents" + this.cid);
				
			};
			
			BaseView.prototype.remove = function(){
				
				this.undelegateEvents();
				
				return this.$el.remove();
			};
			
			return BaseView;
			
	})();
	
	_Message = (function(_super){
		
		__extends(_Message, _super);
		
		function __Message(){
			
			return _Message.__super__.constructor.apply(this, arguments);
			
		}
		
		_Message.prototype.defaults = {
			hideAfter : 10,
			scroll    : true
		};
		
		_Message.prototype.initialize = function(opts){
			
			if(opts == null)
				opts = {};
				
			this.shown = false;
			this.rendered = false;
			this.messenger = opts.messenger;
			
			return this.options = $.extend({}, this.options, opts, this.defaults);
		};
		
		_Message.prototype.show = function(){
			
			var wasShown;
			
			if(!this.rendered)
				this.render();
				
			this.$message.removeClass('messenger-hidden');
			
			wasShown = this.shown;
			
			this.shown = true;
			
			if(!wasShown)
				return this.trigger('show');
		};
		
		_Message.prototype.hide = function(){
			
			var wasShown;
			
			if(!this.rendered)
				return;
				
			this.$message.addClass('messenger-hidden');
			
			wasShown = this.shown;
			
			this.shown = false;
			
			if(wasShown)
				return this.trigger('hide');
		};
		
		_Message.prototype.cancel = function(){
			
			return this.hide();
			
		};
		
		_Message.prototype.update = function(opts){
			
			var _ref2,
				_this = this;
				
			if(_.isString(opts)){
				
				opts = {
					message : opts;
				};
			}
			
			$.extend(this.options, opts);
			
			this.lastUpdate = new Date();
			this.rendered = false;
			this.events = (_ref2 = this.options.events) != null ? _ref2 : {};
			this.render();
			this.actionsToEvents();
			this.delegateEvents();
			this.checkClickable();
			
			if(this.options.hideAfter){
				
				this.$message.addClass('messenger-will-hide-after');
				
				if(this._hideTimeout != null){
					
					clearTimeout(this._hideTimeout);
					
				}
				
				this._hideTimeout = setTimeout(function(){
					
					return _this.hide();
				}, this.options.hideAfter * 1000);
			} else {
				
				this.$message.removeClass('messenger-will-hide-after');
			}
			
			if(this.options.hideOnNavigate){
				
				this.$message.addClass('messenger-will-hide-on-navigate');
				
				if((typeof Backbone !== 'undefined' && Backbone !== null ? Backbone.history : void 0) != null){
					
					Backbone.history.on('route', function(){
						return _this.hide();
					});
				}
			} else {
				this.$message.removeClass('messenger-will-hide-on-navigate');
			}
			
			return this.trigger('update', this);
		};
		
		_Message.prototype.scrollTo = function(){
			
			if(!this.options.scroll)
				return;
				
			return $.scrollTo(this.$el, {
				duration : 400,
				offset : {
					left : 0,
					top: -20
				}
			});
		};
		
		_Message.prototype.timeSinceUpdate = function(){
			
			if(this.lastUpdate){
				
				return (new Date) - this.lastUpdate;
			} else {
				return null;
			}
		};
		
		_Message.prototype.actionsToEvents = function(){
			
			var act,
				name,
				_ref2,
				_results,
				_this = this;
				
			_ref2 = this.options.actions;
			_results = [];
			
			for(name in _ref2){
				
				act = _ref2[name];
				
				_results.push(this.events["click [data-action=\""+name+"\"]a"] = (function(act){
					
					return function(e){
						e.preventDefault();
						e.stopPropagation();
						
						_this.trigger("action:"+name, act, e);
						
						return act.action.call(_this, e, _this);
					};
					
				})(act));
			}
			
			return _results;
		};
		
		_Message.prototype.checkClickable = function(){
			
			var evt,
				name,
				_ref2,
				_results;
				
			_ref2 = this.events;
			_results = [];
			
			for(name in ref2){
				
				evt = _ref2[name];
				
				if(name === 'click'){
					
					_results.push(this.$message.addClass('messenger-clickable'));
				} else {
					_results.push(void 0);
				}
			}
			
			return _results;
		};
		
		_Message.prototype.undelegateEvents = function(){
			
			var _ref2;
			
			_Message.__super.__undelegateEvents.apply(this, arguments);
			
			return (_ref2 = this.$message) != null ? _ref2.removeClass('messenger-clickable') : void 0;
		};
		
		_Message.prototype.parseActions = function(){
			
			var act,
				actions,
				n_act,
				name,
				_ref2, 
				_ref3;
				
				actions = [];
				_ref2 = this.options.actions;
				
				for(name in _ref2){
					
					act = _ref2[name];
					n_act = $.extend({}, act);
					n_act.name = name;
					
					if((_ref3 = n_act.label) == null){
						
						n_act.label = name;
						
					}
					
					actions.push(n_act);
				}
				
				return actions;
		};
		
		_Message.prototype.template = function(opts){
			
			var $action,
				$actions,
				$cancel,
				$link,
				$message,
				$text,
				action,
				_i,
				_len,
				_ref2,
				_this = this;
				
				$message = $("<div class='messenger-message message alrt" + opts.type + " message-" + opts.type + " alert-"+opts.type+"'>");
				
				if(opts.showCloseButton){
					
					$cancel = $('<button type="button" class="messenger-close" data-dismiss="alert">&times;</button>');
					
					$cancel.click(function(){
						
						_this.cancel();
						
						return true;
					});
					
					$message.append($cancel);
				}
				
				$text = $("<div class=\"messenger-message-inner\">"+opts.message+"</div>");
				
				$message.append($text);
				
				if(opts.actions.length){
					
					$actions = $('<div class="messenger-actions">');
					
				}
				
				_ref2 = opts.actions;
				
				for(_i = 0, _len = _ref2.length; _i < _len; _i++){
					
				 	action = _ref2[_i];
					$action = $('<span>');
					$action.attr('data-action', "" + action.name);
					
					$link = $('<a>');
					$link.html(action.label);
					
					$action.append($('<span class="messenger-phrase">'));
					$action.append($link);
					$actions.append($action);
				}
				
				$message.append($actions);
				
				return $message;
		};
		
		_Message.prototype.render = function(){
			
			var opts;
			
			if(this.rendered){
				return;
			}
			
			if(!this._hasSlot){
				
				this.setElement(this.messenger._reserveMessageSlot(this));
				this._hasSlot = true;
			}
			
			opts = $.extend({}, this.options, {
				actions : this.parseActions()
			});
			
			this.$message = $(this.template(opts));
			this.$el.html = (this.$message);
			$this.shown = true;
			$this.rendered = true;
			
			return this.trigger('render');
		};
		
		return _Message;
		
	})(BaseView);
	
	
	RetryingMessage = (function(_super){
		
		__extends(RetryingMessage, __super);
		
		function RetryingMessage(){
			
			return RetryingMessage.__super__.constructor.apply(this, arguments);
			
		}
		
		RetryingMessage.prototype.initialize = function(){
			
			RetryingMessage.__super__.constructor.apply(this, arguments);
			
			return this._timers = {};
		};
		
		RetryingMessage.prototype.cancel = function(){
			
			this.clearTimers();
			this.hide();
			
			if((this._actionInstance != null) && (this._actionInstance.abort != null)){
				
				return this._actionInstance.abort();
				
			}
		};
		
		RetryingMessage.prototype.clearTimers = function(){
			
			var name,
				timer,
				_ref2,
				_ref3;
				
			_ref2 = this._timers;
			
			for(name in ref2){
				
				timer = _ref2[name];
				clearTimeout(timer);
				
			}
			
			this._timers = {};
			
			return (_ref3 = this.$message) != null ? _ref3.removeClass('messenger-retry-soon messenger-retry-later') : void 0;
		};
		
		RetryingMessage.prototype.render = function(){
			
			var action,
				name,
				_ref2,
				_results;
				
			RetryingMessage.__super__.render.apply(this, arguments);
			
			this.clearTimers();
			
			_ref2 = this.options.actions;
			_results = [];
			
			for(name in _ref2){
				
				action = _ref2[name];
				
				if(action.auto){
					
					_results.push(this.startCountdown(name, action));
				} else {
					
					_results.push(void 0);
				}
			}
			
			return _results;
		};
		
		RetryingMessage.prototype.renderPhrase = function(action, time){
			
			var phrase;
			
			phrase = action.phrase.replace('TIME', this.formatTime(time));
			
			return phrase;
		};
		
		RetryingMessage.prototype.formatTime = function(time){
			
			var pluralize;
			
			pluralize = function(num, str){
				
				num = Math.floor(num);
				
				if(num != 1){
					str = str + 's';
				}
				
				return 'in ' + num + ' ' + str;
			};
			
			if(Math.floor(time) === 0){
				return
			}
		}
	})
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	